package com.lw.extraceim.util;

import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.util.Log;
import android.view.View;

import com.baidu.location.BDAbstractLocationListener;
import com.baidu.location.BDLocation;
import com.baidu.location.BDLocationListener;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.baidu.mapapi.map.BaiduMap;
import com.baidu.mapapi.map.BitmapDescriptor;
import com.baidu.mapapi.map.BitmapDescriptorFactory;
import com.baidu.mapapi.map.MapStatus;
import com.baidu.mapapi.map.MapStatusUpdateFactory;
import com.baidu.mapapi.map.MapView;
import com.baidu.mapapi.map.MarkerOptions;
import com.baidu.mapapi.map.MyLocationConfiguration;
import com.baidu.mapapi.map.MyLocationData;
import com.baidu.mapapi.map.OverlayOptions;
import com.baidu.mapapi.map.Polyline;
import com.baidu.mapapi.map.PolylineOptions;
import com.baidu.mapapi.model.LatLng;
import com.lw.extraceim.R;
import com.lw.extraceim.model.PackageRoute;

import java.util.ArrayList;
import java.util.List;

import okhttp3.Route;

/*关于百度地图的工具类*/
public class MapUtils implements SensorEventListener {
    private static final String TAG = "MapUtils";
    private static LocationClient locationClient = null;
    private static LatLng latLng = null;//获取的定位信息
    static BaiduMap mBaiduMap;
    static MapView mMapView;
    private static MyLocationListenner myListener = new MyLocationListenner();
    //起点图标
    static BitmapDescriptor startBD = BitmapDescriptorFactory.fromResource(R.drawable.ic_me_history_startpoint);
    //终点图标
    static BitmapDescriptor finishBD = BitmapDescriptorFactory.fromResource(R.drawable.ic_me_history_finishpoint);
    static int mCurrentDirection = 0;
    static double mCurrentLat = 0.0;
    static double mCurrentLon = 0.0;
    static boolean isFirstLoc = true; // 是否首次定位
    static MyLocationData locData;
    static float mCurrentZoom = 18f;//默认地图缩放比例值
    static List<LatLng> points = new ArrayList<LatLng>();//位置点集合
    static Polyline mPolyline;//运动轨迹图层
    static LatLng last = new LatLng(0, 0);//上一个定位点
    static MapStatus.Builder builder;
    private static int currentState = 0;
    public static final int DRAW_LINE = 1;
    public static final int STOP = 0;

    /*
        使用说明
        1.MapUtils.initClient(UseUtilsActivity.this);使用之前必须初始化
        2.MapUtils.GetLocation();获取经纬度的方法
        3. MapUtils.DrawLine(mapView,true,MapUtils.DRAW_LINE);开始画线
           MapUtils.DrawLine(mapView,false,MapUtils.STOP);停止画线
    * */
    /*使用前必须先调用,初始化定位的设置*/
    public static void initClient(Context context) {

        if (locationClient == null) {
            locationClient = new LocationClient(context);
            LocationClientOption option = new LocationClientOption();
            option.setCoorType("bd09ll");
            option.setOpenGps(true);
            option.setScanSpan(1000);
            option.setPriority(LocationClientOption.NetWorkFirst);
            option.setProdName("MyBaiduMap");
            option.setLocationMode(LocationClientOption.LocationMode.Device_Sensors);//只用gps定位，需要在室外定位
            locationClient.setLocOption(option);
        } else
            return;
    }

    /*获取当前的经纬度LatLng包含经度与维度*/
    public static LatLng GetLocation() {
        if (locationClient != null && !locationClient.isStarted()) {
            locationClient.start();
            locationClient.registerLocationListener(myListener);
        }
        return latLng;
    }

    /*画线的方法*/
    public static void DrawLine(MapView mapView, boolean isStart, int state) {
        currentState = state;
        if (isStart) {

            mBaiduMap = mapView.getMap();
            mMapView = mapView;
            mBaiduMap.setMyLocationEnabled(true);
            mBaiduMap.setMyLocationConfiguration(new MyLocationConfiguration(
                    com.baidu.mapapi.map.MyLocationConfiguration.LocationMode.FOLLOWING, true, null));
            /**
             * 添加地图缩放状态变化监听，当手动放大或缩小地图时，拿到缩放后的比例，然后获取到下次定位，
             *  给地图重新设置缩放比例，否则地图会重新回到默认的mCurrentZoom缩放比例
             */
            mBaiduMap.setOnMapStatusChangeListener(new BaiduMap.OnMapStatusChangeListener() {

                @Override
                public void onMapStatusChangeStart(MapStatus arg0) {
                    // TODO Auto-generated method stub

                }

                @Override
                public void onMapStatusChangeStart(MapStatus mapStatus, int i) {

                }

                @Override
                public void onMapStatusChangeFinish(MapStatus arg0) {
                    mCurrentZoom = arg0.zoom;
                }

                @Override
                public void onMapStatusChange(MapStatus arg0) {
                    // TODO Auto-generated method stub
                }
            });
            //开始画线
            if (locationClient != null && !locationClient.isStarted()) {
                locationClient.start();
                locationClient.registerLocationListener(myListener);

            }
            mBaiduMap.clear();
        } else {

            //想终止画线
            if (locationClient != null && locationClient.isStarted()) {
                locationClient.stop();
                locationClient.unRegisterLocationListener(myListener);
                if (isFirstLoc) {
                    points.clear();
                    last = new LatLng(0, 0);
                    return;
                }

                MarkerOptions oFinish = new MarkerOptions();// 地图标记覆盖物参数配置类
                oFinish.position(points.get(points.size() - 1));
                oFinish.icon(finishBD);// 设置覆盖物图片
                mBaiduMap.addOverlay(oFinish); // 在地图上添加此图层
                //复位
                points.clear();
                last = new LatLng(0, 0);
                isFirstLoc = true;
            }
        }
    }

    /*停止监听，在onDestroy方法中调用*/
    public static void stopClient() {
        if (locationClient != null && locationClient.isStarted()) {
            locationClient.stop();
            locationClient.unRegisterLocationListener(myListener);
            locationClient = null;
        }
    }

    double lastX;

    @Override
    public void onSensorChanged(SensorEvent sensorEvent) {
        double x = sensorEvent.values[SensorManager.DATA_X];

        if (Math.abs(x - lastX) > 1.0) {
            mCurrentDirection = (int) x;
            if (isFirstLoc) {
                lastX = x;
                return;
            }

            locData = new MyLocationData.Builder().accuracy(0)
                    // 此处设置开发者获取到的方向信息，顺时针0-360
                    .direction(mCurrentDirection).latitude(mCurrentLat).longitude(mCurrentLon).build();
            mBaiduMap.setMyLocationData(locData);
        }
        lastX = x;

    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {

    }

    private static LatLng getMostAccuracyLocation(BDLocation location) {

        if (location.getRadius() > 40) {//gps位置精度大于40米的点直接弃用
            return null;
        }

        LatLng ll = new LatLng(location.getLatitude(), location.getLongitude());

        points.add(ll);
        last = ll;
        //有5个连续的点之间的距离小于10，认为gps已稳定，以最新的点为起始点
        if (points.size() >= 5) {
            points.clear();
            return ll;
        }
        return null;
    }

    private static void locateAndZoom(final BDLocation location, LatLng ll) {
        mCurrentLat = location.getLatitude();
        mCurrentLon = location.getLongitude();
        locData = new MyLocationData.Builder().accuracy(0)
                // 此处设置开发者获取到的方向信息，顺时针0-360
                .direction(mCurrentDirection).latitude(location.getLatitude())
                .longitude(location.getLongitude()).build();
        mBaiduMap.setMyLocationData(locData);

        builder = new MapStatus.Builder();
        builder.target(ll).zoom(mCurrentZoom);//设置地图中心点为target，缩放为mCurrentZoom
        mBaiduMap.animateMapStatus(MapStatusUpdateFactory.newMapStatus(builder.build()));
    }

    public static class MyLocationListenner implements BDLocationListener {

        @Override
        public void onReceiveLocation(final BDLocation location) {

            if (locationClient == null && !locationClient.isStarted())
                return;
            latLng = new LatLng(location.getLatitude(), location.getLongitude());
            if (locationClient.isStarted() && currentState == DRAW_LINE) {
                if (location == null || mMapView == null) {
                    return;
                }
                //注意这里只接受gps点，需要在室外定位。
                if (location.getLocType() == BDLocation.TypeGpsLocation) {
                    if (isFirstLoc) {
                        //首次定位
                        //第一个点很重要，决定了轨迹的效果，gps刚开始返回的一些点精度不高，尽量选一个精度相对较高的起始点
                        LatLng ll = null;
                        ll = getMostAccuracyLocation(location);
                        if (ll == null) {
                            return;
                        }
                        isFirstLoc = false;
                        points.add(ll);//加入集合
                        last = ll;
                        //显示当前定位点，缩放地图
                        locateAndZoom(location, ll);
                        //标记起点图层位置
                        MarkerOptions oStart = new MarkerOptions();// 地图标记覆盖物参数配置类
                        oStart.position(points.get(0));// 覆盖物位置点，第一个点为起点
                        oStart.icon(startBD);// 设置覆盖物图片
                        mBaiduMap.addOverlay(oStart); // 在地图上添加此图层
                        return;//画轨迹最少得2个点，首次定位到这里就可以返回了
                    }
                    //从第二个点开始
                    LatLng ll = new LatLng(location.getLatitude(), location.getLongitude());
                    //sdk回调gps位置的频率是1秒1个，位置点太近动态画在图上不是很明显，可以设置点之间距离大于为5米才添加到集合中
                    points.add(ll);//如果要运动完成后画整个轨迹，位置点都在这个集合中
                    last = ll;
                    //显示当前定位点，缩放地图
                    locateAndZoom(location, ll);
                    //清除上一次轨迹，避免重叠绘画
                    mMapView.getMap().clear();
                    //起始点图层也会被清除，重新绘画
                    MarkerOptions oStart = new MarkerOptions();
                    oStart.position(points.get(0));
                    oStart.icon(startBD);
                    mBaiduMap.addOverlay(oStart);
                    //将points集合中的点绘制轨迹线条图层，显示在地图上
                    OverlayOptions ooPolyline = new PolylineOptions().width(13).color(0xAAFF0000).points(points);
                    mPolyline = (Polyline) mBaiduMap.addOverlay(ooPolyline);
                }
            }
        }
    }

    //返回两个经纬度点的距离，单位米
    public static double getDistance(LatLng start, LatLng end) {
        //纬度
        double lat1 = (Math.PI / 180) * start.latitude;
        double lat2 = (Math.PI / 180) * end.latitude;
        //经度
        double lon1 = (Math.PI / 180) * start.longitude;
        double lon2 = (Math.PI / 180) * end.longitude;
        //地球的半径
        double R = 6371;
        double result = Math.acos(Math.sin(lat1) * Math.sin(lat2) + Math.cos(lat1) * Math.cos(lat2) * Math.cos(lon2 - lon1)) * R;
        return result * 1000;
    }


    /**
     * 讲PackageRoute转换文LatLng
     *
     * @param routeList
     * @return
     */
    public static List<LatLng> coordinateConvert(List<PackageRoute> routeList) {
        List<LatLng> latLngs = new ArrayList<LatLng>();
        double lanSum = 0;
        double lonSum = 0;
        for (PackageRoute packageRoute : routeList) {
            LatLng latLng = new LatLng(packageRoute.getX(), packageRoute.getY());
            latLngs.add(latLng);

            lanSum += latLng.latitude;
            lonSum += latLng.longitude;
        }
        Log.d(TAG, "coordinateConvert: " + latLngs);
        return latLngs;
    }
}

